use crate::{
    error::ServerError, protocol::{
        service::{addr2id, Addr, MountResponseD, ServiceMetaD, SessionKey, TasksMetaD},
        task::{NominalTask, SymbolicTask},
        workflow::NominalWorkflow
    }, workflows::manager::WORKFLOW_MANAGER
};
use reqwest::StatusCode;
use rocket::http::Status;
use serde::{Serialize, Deserialize};
use std::sync::{Arc, Mutex};

#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum ServiceStatus {
    CannotReach,
    ServiceError(String),
    ClientError,
    Registered,
    Mounted,
    Running,
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub enum ServiceType {
    HTTP,
    ZMQ,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Service {
    pub tpe: ServiceType,
    pub address: Addr,
    pub name: String,
    given_name: Option<String>,
    category: Option<String>,
    description: Option<String>,
    tasks: Vec<NominalTask>,
    workflows: Vec<NominalWorkflow>,
    pub status: ServiceStatus,
    recv: Option<ServiceStructA>,
    pub session_key: Option<SessionKey>
}

impl Service {
    pub fn new(address: Addr) -> Result<Self, ServerError> {
        let tpe = if address.starts_with("http://") || address.starts_with("https://") {
            ServiceType::HTTP
        } else if address.starts_with("tcp://") {
            ServiceType::ZMQ
        } else {
            return Err(ServerError::ServiceErrorStr("不支持的服务类型"));
        };
        Ok(Self { 
            tpe,
            address, 
            tasks: Vec::new(), 
            status: ServiceStatus::CannotReach, 
            description: None, 
            name: "".to_string(), 
            given_name: None, 
            workflows: Vec::new(),
            category: None,
            recv: None,
            session_key: None
        })
    }

    pub fn from_recv(recv: ServiceStructA) -> Result<Self, ServerError> {
        let mut service = Self::new(recv.address.clone())?;
        service.recv = Some(recv);
        Ok(service)
    }

    pub fn add_task(mut self, task: NominalTask) -> Self {
        self.tasks.push(task);
        self
    }

    pub fn get_session_key(&self) -> String {
        self.session_key.clone().unwrap_or_default()
    }

    pub async fn register(&mut self) -> Result<(), ServerError> {
        if self.tpe == ServiceType::HTTP {
            match reqwest::get(format!("{}/", self.address)).await {
                Ok(response) => {
                    let desc = response.text().await.map_err(|e|ServerError::ServiceError(e.to_string()))?;
                }
                Err(e) => {
                    return Err(ServerError::ServiceError(e.to_string()));
                }
            }

            // 访问address/meta 获取名称、描述和分类信息
            match reqwest::get(format!("{}/meta", self.address)).await {
                Ok(response) => {
                    let meta = response.text().await.map_err(|e|ServerError::ServiceError(e.to_string()))?;
                    let meta_json: ServiceMetaD = serde_json::from_str(&meta).map_err(|e|ServerError::ServiceError(e.to_string()))?;
                    if let Some(name) =  meta_json.name {
                        self.name = name
                    } else {
                        self.name = "无名服务".to_string()
                    }
                    self.description = meta_json.desc;
                    self.category = meta_json.category;
                }
                Err(e) => {
                    return Err(ServerError::ServiceError(e.to_string()));
                }
            }

            // 访问address/task获取任务列表
            match reqwest::get(format!("{}/tasks", self.address)).await {
                Ok(response) => {
                    if response.status().is_success() {
                        let str_tasks = response.text().await.unwrap_or("[]".to_string());
                        let task_vec: Vec<String> = serde_json::from_str(&str_tasks).unwrap_or_else(|_| {
                            println!("外部服务任务列表解析错误: {}", str_tasks);
                            vec![]
                        });
                        let mut task_vec_clean = vec![];
                        for each in task_vec {
                            task_vec_clean.push(each.replace(' ', ""));
                        }
                        self.tasks = task_vec_clean;
                    } else {
                        println!("获取任务列表失败，状态码: {}", response.status());
                        self.tasks = Vec::new();
                    }
                }
                Err(e) => {
                    println!("获取任务列表失败: {}", e);
                    self.tasks = Vec::new();
                    return Err(ServerError::ServiceError(e.to_string()));
                }
            }
        } else {
            let context = zmq::Context::new();
            let socket = context.socket(zmq::REQ).unwrap();
            socket.connect(&self.address).unwrap();
            socket.send("/", 0).unwrap();
            let buffer = &mut [0; 1024];
            socket.recv_into(buffer, 0).unwrap();
            let desc = String::from_utf8(buffer.to_vec()).unwrap();

            socket.send("/meta", 0).unwrap();
            socket.recv_into(buffer, 0).unwrap();
            let meta = String::from_utf8(buffer.to_vec()).unwrap();
            let meta_json: ServiceMetaD = serde_json::from_str(&meta).unwrap();
            if let Some(name) =  meta_json.name {
                self.name = name
            } else {
                self.name = "无名服务".to_string()
            }
            self.description = meta_json.desc;
            self.category = meta_json.category;

            socket.send("/tasks", 0).unwrap();
            socket.recv_into(buffer, 0).unwrap();
            let tasks = String::from_utf8(buffer.to_vec()).unwrap();
            let task_vec: Vec<String> = serde_json::from_str(&tasks).unwrap_or_else(|_| {
                println!("外部服务任务列表解析错误: {}", tasks);
                vec![]
            });
            let mut task_vec_clean = vec![];
            for each in task_vec {
                task_vec_clean.push(each.replace(' ', ""));
            }
            self.tasks = task_vec_clean;
            // 关闭socket
            socket.disconnect(&self.address).unwrap();
        }

        if !self.tasks.is_empty() {
            let mut workflow_manager = WORKFLOW_MANAGER.get().unwrap().lock().unwrap();
            for task in &self.tasks {
                let mut symbolic_task = SymbolicTask::try_parse_loose(task)?;
                symbolic_task.name = format!("{}.{}", self.name, symbolic_task.name);
                workflow_manager.add_task(symbolic_task, addr2id(self.address.clone()))?;
            }
        }

        println!("{} service registered", self.address);
        self.status = ServiceStatus::Registered;
        Ok::<(), ServerError>(())
    }

    pub fn merge_given_info(&mut self) {
        let recv = self.recv.take().unwrap();
        self.given_name = recv.given_name;
        self.category = recv.category;
    }

    pub async fn mount(&mut self) -> Result<(), ServerError> {
        match self.status {
            ServiceStatus::CannotReach => Err(ServerError::ServiceErrorStr("请先成功注册")),
            ServiceStatus::ClientError | ServiceStatus::ServiceError(_) => Err(ServerError::ServiceErrorStr("请先重置状态")),
            ServiceStatus::Mounted | ServiceStatus::Running => Ok(()),
            ServiceStatus::Registered => {
                if self.tpe == ServiceType::HTTP {
                    match reqwest::Client::new()
                        .get(format!("{}/mount", self.address))
                        .body("main system")
                        .send()
                        .await {
                            Ok(response) => { 
                            if response.status() == StatusCode::OK {
                                let txt = response.text().await.map_err(|e|ServerError::ServiceError(e.to_string()))?; 
                                let resp: MountResponseD = serde_json::from_str(&txt).map_err(|e|ServerError::ServiceError(format!("挂载失败: {}", e.to_string())))?;
                                self.session_key = Some(resp.session_key);
                                self.status = ServiceStatus::Mounted;
                                println!("挂载成功: {}", self.address);
                                Ok(())
                            } else {
                                return Err(ServerError::ServiceError(format!("挂载失败: {}", response.text().await.unwrap_or("".to_string()))));
                            }
                        },
                        Err(e) => Err(ServerError::ServiceError(e.to_string()))
                    }
                } else {
                    let context = zmq::Context::new();
                    let socket = context.socket(zmq::REQ).unwrap();
                    socket.connect(&self.address).unwrap();
                    socket.send("/mount", 0).unwrap();
                    let buffer = &mut [0; 1024];
                    socket.recv_into(buffer, 0).unwrap();
                    let txt = String::from_utf8(buffer.to_vec()).map_err(|e|ServerError::ServiceError(format!("挂载失败: {}", e.to_string())))?;
                    let resp: MountResponseD = serde_json::from_str(&txt).map_err(|e|ServerError::ServiceError(format!("挂载失败: {}", e.to_string())))?;
                    self.session_key = Some(resp.session_key);
                    self.status = ServiceStatus::Mounted;
                    println!("挂载成功: {}", self.address);
                    Ok(())
                }
            }
        }
    }

    pub fn try_resolve_symbolic_task(&self) -> Result<(), ServerError> {
        for task in &self.tasks {
            let _ = SymbolicTask::try_parse_loose(task)?;
        }
        Ok(())
    }

    pub fn get_task(&self, task_name: &String) -> Option<SymbolicTask> {
        let prefix = task_name.clone() + ":";
        for task in &self.tasks {
            if task.starts_with(&prefix) {
                if let Ok(sym) = SymbolicTask::try_parse_loose(task) {
                    return Some(sym)
                } else {
                    println!("task parse error: {}", task);
                }
            }
        }
        None
    }
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ServiceStructA {
    pub address: Addr,
    given_name: Option<String>,
    category: Option<String>,
    description: Option<String>,
    tasks: Option<Vec<NominalTask>>,
    workflows: Option<Vec<NominalWorkflow>>,
}

